#![no_main]
#![no_std]
#![allow(unused)]
#![feature(panic_info_message)]

mod batch;
mod lang_items;
mod logging;
mod sbi;
mod sync;
pub mod syscall;
pub mod trap;

#[macro_use]
mod console;

use core::arch::global_asm;

use log::{debug, error, info, trace, warn};
global_asm!(include_str!("entry.asm"));
global_asm!(include_str!("link_app.S"));

extern "C" {
    // 这里的变量名代表一个地址，变量中的值并没有初始化（值不是地址）
    // 可以不使用#[link_name]这个宏，变量名就是链接脚本中的符号
    #[link_name = "sbss"]
    pub static mut sbss: usize;
    #[link_name = "ebss"]
    pub static mut ebss: usize;
    //不能同时声明为变量符号和方法符号
    // fn sbss(); // start addr of BSS segment
    // fn ebss(); // end addr of BSS segment
}

#[no_mangle]
pub fn rust_main() -> ! {
    extern "C" {
        fn stext(); // begin addr of text segment
        fn etext(); // end addr of text segment
        fn srodata(); // start addr of Read-Only data segment
        fn erodata(); // end addr of Read-Only data ssegment
        fn sdata(); // start addr of data segment
        fn edata(); // end addr of data segment
        fn boot_stack_lower_bound(); // stack lower bound
        fn boot_stack_top(); // stack top
    }
    clear_bss();
    logging::init();
    println!("[kernel] Hello, world!");
    trace!(
        "[kernel] .text [{:#x}, {:#x})",
        stext as usize,
        etext as usize
    );
    debug!(
        "[kernel] .rodata [{:#x}, {:#x})",
        srodata as usize, erodata as usize
    );
    info!(
        "[kernel] .data [{:#x}, {:#x})",
        sdata as usize, edata as usize
    );
    warn!(
        "[kernel] boot_stack top=bottom={:#x}, lower_bound={:#x}",
        boot_stack_top as usize, boot_stack_lower_bound as usize
    );
    unsafe {
        error!("[kernel] .bss [{:#x}, {:#x})", sbss as usize, ebss as usize);
    }
    trap::init();
    batch::init();
    batch::run_next_app();
}

fn clear_bss() {
    /*方式一*/
    // extern "C" {
    //     fn sbss();
    //     fn ebss();
    // }
    // (sbss as usize..ebss as usize).for_each(|a| {
    //     unsafe { (a as *mut u8).write_volatile(0) }
    // });

    /*方式二*/

    unsafe {
        let ptr = &mut sbss as *mut usize as *mut u8;
        let end = &mut ebss as *mut usize as *mut u8;
        let len = end as usize - ptr as usize;
        core::slice::from_raw_parts_mut(ptr, len).fill(0);
        // while ptr < end {
        //     ptr.write_volatile(0);
        //     ptr = ptr.offset(1);
        // }
    }
}
